
#include "stdafx.h"
#include "BreakpointsWnd.h"
#include "MainFrm.h"
#include "XortStudio.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBreakpointsWnd

CBreakpointsWnd::CBreakpointsWnd()
{
}

CBreakpointsWnd::~CBreakpointsWnd()
{
}

BEGIN_MESSAGE_MAP(CBreakpointsWnd, CDockablePane)
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_NOTIFY(NM_DBLCLK, IDD_STACK_LISTCTRL, OnBreackpointListNotify)
END_MESSAGE_MAP()

int CBreakpointsWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if( CDockablePane::OnCreate( lpCreateStruct ) == -1 )
        return -1;

    CRect rectDummy( 0, 0, 400, 200 );
    if( !m_listCtrl.Create( WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_EDITLABELS|WS_HSCROLL|WS_VSCROLL|LVS_SINGLESEL, 
        rectDummy, this, IDD_STACK_LISTCTRL ) )
    {
        TRACE0("Failed to create output tab window\n");
        return -1;      // fail to create
    }

    m_listCtrl.SetExtendedStyle( LVS_EX_FLATSB|LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT );

    m_listCtrl.InsertColumn( 1, "Line #", LVCFMT_LEFT, 80 );
    m_listCtrl.InsertColumn( 2, "Method", LVCFMT_LEFT, 160 );
    m_listCtrl.InsertColumn( 3, "IP", LVCFMT_LEFT, 80 );
    
    return 0;
}

int CALLBACK SortItemsCB( LPARAM lp1, LPARAM lp2, LPARAM lp3 )
{
    return (int)( lp1 - lp2 );
}

void CBreakpointsWnd::AddBreakpoint( DWORD dwLine, DWORD dwIP, LPCSTR lpszMethodName )
{
    CString csFmt;
    csFmt.Format( "%d", dwLine );

    int iItem = m_listCtrl.InsertItem( LVIF_TEXT | LVIF_STATE | LVIF_PARAM, m_listCtrl.GetItemCount(), csFmt, 0, LVIS_SELECTED, 0, dwLine );
    m_listCtrl.SetItemText( iItem, 1, lpszMethodName );

    csFmt.Format( "%08d", dwIP );
    m_listCtrl.SetItemText( iItem, 2, csFmt );

    m_listCtrl.SortItems( &SortItemsCB, (DWORD_PTR)this );
}

void CBreakpointsWnd::RemoveBreakpoint( DWORD dwLine )
{
    LVFINDINFO fi;
    fi.flags = LVFI_PARAM;
    fi.lParam = dwLine;
    
    int iIdx = m_listCtrl.FindItem( &fi );
    if( iIdx != -1 ) {
        m_listCtrl.DeleteItem( iIdx );
    }
}

void CBreakpointsWnd::OnSize(UINT nType, int cx, int cy)
{
    CDockablePane::OnSize(nType, cx, cy);

    // Tab control should cover the whole client area:
    m_listCtrl.SetWindowPos( NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
}

void CBreakpointsWnd::OnBreackpointListNotify(NMHDR* pNMHDR, LRESULT* pResult)
{
    if( pNMHDR )
    {
        if( pNMHDR->code == NM_DBLCLK )
        {
            DWORD dwPos = GetMessagePos();
            CPoint pt( GET_X_LPARAM( dwPos ), GET_Y_LPARAM ( dwPos ) ); 

            m_listCtrl.ScreenToClient( &pt ); 

            UINT test; 
            int iIdx = m_listCtrl.HitTest( pt, &test ); 

            if( iIdx != -1 && ( test & LVHT_ONITEM ) ) // Is the click actually *on* the item?
            { 
                DWORD dwLineIdx = m_listCtrl.GetItemData( iIdx );
                CXortStudioDoc *pDoc = GET_ACTIVE_DOC(CXortStudioDoc);
                pDoc->LocateLineInView( dwLineIdx );
            }
        }
    }

    *pResult = TRUE;
}
